/*
 * Copyright 2010-2012 Susanta Tewari. <freecode4susant@users.sourceforge.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
* FullMap.java
*
* Created on January 3, 2008, 5:34 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
 */
package genomemap.maps;

import genomemap.data.DataSource;
import genomemap.data.PDataSource;

import javautil.collections.ArrayUtil;
import javautil.graphics.GraphicsUtil;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.Serializable;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

/**
 *
 * @author stewari1
 */
public class FullHybridizationMapComponent extends JComponent {

    /** Field description */
    private int CANVAS_HEIGHT = 0;

    /** Field description */
    private int CANVAS_WIDTH = 0;

    /** Field description */
    private int VERTICAL_GAP = 0;

    /** Field description */
    private int FONT_HEIGHT = 2;

    /** Field description */
    private final int X_INDENT = 10;

    /** Field description */
    private final int Y_INDENT = 10;

    /** Field description */
    private String[] mapLines = null;

    /** Field description */
    private final Font font = new Font("Courier New", Font.BOLD, 6);

    /** Field description */
    private int contigCount = 0;

    /** Field description */
    private FullHybridizationMap fullHybridizationMap;

    /** Creates a new instance of FullMap */
    public FullHybridizationMapComponent() {}

    /**
     * Constructs ...
     *
     * @param pData description
     */
    private FullHybridizationMapComponent(PDataSource pData) {

        this.fullHybridizationMap = new FullHybridizationMap(pData);

        fullHybridizationMap.build();

        this.mapLines = fullHybridizationMap.getMapString().split("\\n");


        // add listeners
        addMouseListener(new MouseAdapterImpl());
        addMouseMotionListener(new MouseAdapterImpl());


        // calculate the drawing area
        // ideally font height should be used in the following way but since this is too big
        // we want to show only a compressed map
        // FONT_HEIGHT = getFontMetrics(font).getHeight();
        this.CANVAS_HEIGHT = (mapLines.length - 1) * VERTICAL_GAP + mapLines.length * FONT_HEIGHT;
        this.CANVAS_WIDTH = ArrayUtil.findMax(GraphicsUtil.getPixelWidth(mapLines,
                getFontMetrics(font)));
    }

    /**
     * Constructs ...
     *
     * @param ch_id description
     * @param probeOrder description
     */
    public FullHybridizationMapComponent(int ch_id, int[] probeOrder) {
        this(DataSource.getPDataSource(ch_id, probeOrder));
    }

    @Override
    public void paintComponent(Graphics g) {

        Graphics2D g2 = (Graphics2D) g;

        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setStroke(new BasicStroke(2.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
        g2.setFont(font);
        g2.setColor(Color.white);
        g2.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
        g2.setColor(Color.BLACK);

        for (int i = 0; i < mapLines.length; i++) {

            g2.drawString(mapLines[i], X_INDENT, Y_INDENT + (i - 1) * (VERTICAL_GAP + FONT_HEIGHT));
        }
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT);
    }

    @Override
    public int getWidth() {
        return CANVAS_WIDTH;
    }

    @Override
    public int getHeight() {
        return CANVAS_HEIGHT;
    }

    void compress() {

        this.VERTICAL_GAP = 0;

        repaint();
    }

    void expand() {

        this.FONT_HEIGHT = 2;

        repaint();
    }

    public int getVerticalGap() {
        return VERTICAL_GAP;
    }

    public void setVerticalGap(int verticalGap) {
        this.VERTICAL_GAP = verticalGap;
    }

    public int getContigCount() {
        return contigCount;
    }

    public void setContigCount(int contigCount) {
        this.contigCount = contigCount;
    }

    /**
     * Class description
     *
     * @version        Enter version here..., 12/11/23
     * @author         Susanta Tewari
     */
    private class MouseAdapterImpl extends MouseAdapter implements Serializable {

        /** Field description */
        private Action compressMapAction = null;

        /** Field description */
        private Action expandMapAction = null;

        /** Field description */
        private Action textMapAction = null;

        /**
         * Constructs ...
         */
        public MouseAdapterImpl() {

            compressMapAction = new AbstractAction("Compress Map") {

                public void actionPerformed(ActionEvent e) {
                    compress();
                }
            };
            expandMapAction = new AbstractAction("Expand Map") {

                public void actionPerformed(ActionEvent e) {
                    expand();
                }
            };
            textMapAction = new AbstractAction("Text Map") {

                public void actionPerformed(ActionEvent e) {

                    JTextArea textArea = new JTextArea();

                    textArea.setText(fullHybridizationMap.getMapString());

                    JDialog dialog = new JDialog(new javax.swing.JFrame(), true);

                    dialog.add(new JScrollPane(textArea));
                    dialog.setSize(500, 600);
                    dialog.setLocationRelativeTo(null);
                    dialog.setVisible(true);
                }
            };
        }

        @Override
        public void mouseReleased(MouseEvent e) {

            if (e.isPopupTrigger()) {

                int x                 = e.getX();
                int y                 = e.getY();
                JPopupMenu jPopupMenu = new JPopupMenu();

                jPopupMenu.add(compressMapAction);
                jPopupMenu.add(expandMapAction);
                jPopupMenu.add(textMapAction);
                jPopupMenu.show(FullHybridizationMapComponent.this, x, y);
            }
        }

        @Override
        public void mouseMoved(MouseEvent e) {

            int x = e.getX();
            int y = e.getY();


            // get the String position
            int FONT_HEIGHT = getFontMetrics(font).getHeight();
            int strPos      = (int) ((double) (y - VERTICAL_GAP) / (VERTICAL_GAP + FONT_HEIGHT)
                                     + 1);

            if (strPos < 0) {
                strPos = 0;
            }

            if (strPos >= mapLines.length) {
                strPos = mapLines.length - 1;
            }


            // display a popup of the string
            JPopupMenu popupMenu = new JPopupMenu();

            popupMenu.add(new JLabel(mapLines[strPos]));
            popupMenu.show(FullHybridizationMapComponent.this, x + 20, y);
        }
    }
}
